/* 
Copyright 2005-2009, Foundations of Success, Bethesda, Maryland 
(on behalf of the Conservation Measures Partnership, "CMP") and 
Beneficent Technology, Inc. ("Benetech"), Palo Alto, California. 

This file is part of Miradi

Miradi is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License version 3, 
as published by the Free Software Foundation.

Miradi is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Miradi.  If not, see <http://www.gnu.org/licenses/>. 
*/ 

package org.miradi.diagram.coalescer;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.miradi.objects.DiagramFactor;
import org.miradi.objects.DiagramLink;

class Node
{
	public Node(DiagramFactor factor)
	{
		this.factor = factor;
		this.linksTo = new HashMap<Integer,Set<Node>>();
		this.isLinkedFrom = new HashMap<Integer,Set<Node>>();
	}

	public void setGroup(Group group)
	{
		assert group.getNodes().contains(this) : "Group must contain this node!";
		assert !isGrouped() : "Node is already grouped!!!";
		
		this.group = group;
		for (Group other : GroupManager.getGroups()) 
		{
			if (!group.equals(other)) 
				other.remove(this);
		}
	}
	
	public boolean isGrouped() {
		return null!=group && group.getNodes().size() > 1;
	}
	
	public Group getGroup()
	{
		return group;
	}

	public DiagramFactor getFactor()
	{
		return factor;
	}
	
	public void add(int direction, Node... nodes) {
		Map<Integer,Set<Node>> map = direction == DiagramLink.TO
								   ? linksTo
							       : direction == DiagramLink.FROM
							       ? isLinkedFrom
							       : null;
		for (Node node : nodes) {
			int type = node.getFactor().getWrappedType();
			Set<Node> existingNodes = getNonNullSet(map, type);
			existingNodes.add(node);
		}		
	}
	
	public Map<Integer,Set<Node>> getLinksTo()
	{
		return linksTo;
	}	

	public Map<Integer,Set<Node>> getIsLinkedFrom()
	{
		return isLinkedFrom;
	}
	
	public Map<Integer,Set<Node>> getLinkedNodes(int direction) {
		switch (direction) 
		{
		case DiagramLink.FROM: return getIsLinkedFrom();
		case DiagramLink.TO: return getLinksTo();
		default: return null;
		}
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + ((factor == null) ? 0 : factor.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Node other = (Node) obj;
		if (factor == null)
		{
			if (other.factor != null)
				return false;
		} else if (!factor.equals(other.factor))
			return false;
		return true;
	}	

	private Set<Node> getNonNullSet(Map<Integer,Set<Node>> map, int type) {
		Set<Node> set = map.get(type);
		if (null==set) 
		{
			set = new HashSet<Node>();
			map.put(type, set);
		}
		return set;		
	}

	private final DiagramFactor factor;
	private final Map<Integer,Set<Node>> linksTo;
	private final Map<Integer,Set<Node>> isLinkedFrom;
	private Group group;
}